//
//  SHPayManager.m
//  SHWeChatAliPay
//
//  Created by 索晓晓 on 2021/10/26.
//

#import "SHPayManager.h"
#import <CommonCrypto/CommonDigest.h>

@interface SHPayManager ()

@property (nonatomic , strong) NSString *appid;
@property (nonatomic , strong) NSString *appSecret;
@property (nonatomic , strong) NSString *merchantKey;
@property (nonatomic , strong) void(^payComplateBlock)(NSDictionary *info);
@property (nonatomic , strong) void(^loginComplateBlock)(NSDictionary *info);

@end

@implementation SHPayManager

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static SHPayManager *instance = nil;
    dispatch_once(&onceToken,^{
        instance = [[SHPayManager alloc] init];
    });
    return instance;
}

/// 注册微信
/// @param appid appid
/// @param universalLink link
+ (void)registerApp:(NSString *)appid
          appSecret:(NSString * _Nullable)appSecret
        merchantKey:(NSString * _Nullable)merchantKey
      universalLink:(NSString * _Nullable)universalLink {
    if (appid && universalLink) {
        [SHPayManager sharedInstance].appid = appid;
        [SHPayManager sharedInstance].appSecret = appSecret;
        [SHPayManager sharedInstance].merchantKey = merchantKey;
        [WXApi registerApp:appid universalLink:universalLink];
    }
#if DEBUG
    [WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString * _Nonnull log) {
        NSLog(@"WeChatLog: %@",log);
    }];
#endif
}

+ (void)stopWXLog {
    [WXApi stopLog];
}

/**
 @brief 处理微信url, 如果wechatSDK不能处理该url，则返回false

 @param url url
 @return 微信能处理, 返回true, 否则返回false
 */
+ (BOOL)openURL:(NSURL*)url {
    
    return [WXApi handleOpenURL:url delegate:[SHPayManager sharedInstance]];
}

/*! @brief 处理微信通过Universal Link启动App时传递的数据
 *
 * 需要在 application:continueUserActivity:restorationHandler:中调用。
 * @param userActivity 微信启动第三方应用时系统API传递过来的userActivity
 * @return 成功返回YES，失败返回NO。
 */
+ (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity {
    
    return [WXApi handleOpenUniversalLink:userActivity delegate:[SHPayManager sharedInstance]];
}

/// 微信支付
/// @param dict 支付需要用到的数据
/// @param complate 完成后的回调
+ (void)payInfo:(NSDictionary *)dict
       complate:(void(^)(NSDictionary *dict))complate {
    
    [SHPayManager sharedInstance].payComplateBlock = nil;
    [SHPayManager sharedInstance].payComplateBlock = complate;
    [self wechatPayOrderDict:dict];
}

//微信支付
+ (void)wechatPayOrderDict:(NSDictionary *)dict{
    
    NSLog(@"signParams ============ %@",dict);
    
    NSString *result = dict[@"sign"];
    if ([SHPayManager sharedInstance].merchantKey) {
            
        //  创建发起支付时的sign签名
        NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
        [signParams setObject:[SHPayManager sharedInstance].appid forKey:@"appid"];//微信appid
        [signParams setObject:[NSString stringWithFormat:@"%@",dict[@"noncestr"]] forKey:@"noncestr"];//随机字符串
        [signParams setObject:@"Sign=WXPay" forKey:@"package"];//扩展字段  参数为 Sign=WXPay
        [signParams setObject:[NSString stringWithFormat:@"%@",dict[@"partnerid"]] forKey:@"partnerid"];//商户账号
        [signParams setObject:[NSString stringWithFormat:@"%@",dict[@"prepayid"]] forKey:@"prepayid"];//此处为统一下单接口返回的预支付订单号
        [signParams setObject:[NSString stringWithFormat:@"%u",[dict[@"timeString"] intValue]] forKey:@"timestamp"];//时间戳
        NSMutableString *contentString  =[NSMutableString string];
        NSArray *keys = [signParams allKeys];
        //  按字母顺序排序
        NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            return [obj1 compare:obj2 options:NSNumericSearch];
        }];
        //  拼接字符串
        for (NSString *categoryId in sortedArray) {
            if (   ![[signParams objectForKey:categoryId] isEqualToString:@""]
                && ![[signParams objectForKey:categoryId] isEqualToString:@"sign"]
                && ![[signParams objectForKey:categoryId] isEqualToString:@"key"]
                )
            {
                [contentString appendFormat:@"%@=%@&", categoryId, [signParams objectForKey:categoryId]];
            }
        }
        //  添加商户密钥key字段  API 密钥
        [contentString appendFormat:@"key=%@", [SHPayManager sharedInstance].merchantKey];
        result = [self md5:contentString];//md5加密
    }

    //调起微信支付 model 为自己服务器返回的参数
    PayReq *req = [[PayReq alloc] init];

    req.openID = [SHPayManager sharedInstance].appid;

    req.partnerId = dict[@"partnerid"];

    req.prepayId = dict[@"prepayid"];

    req.package = @"Sign=WXPay";

    req.nonceStr = dict[@"noncestr"];

    req.timeStamp = [dict[@"timeString"] intValue];

    req.sign = result;
    
    [WXApi sendReq:req completion:^(BOOL success) {
        if (!success) {
            
            NSString *message = @"发送请求到微信失败，请稍后再试";

            if (![WXApi isWXAppInstalled]) {
                message = @"未安装微信";
            } else {
                if (![WXApi isWXAppSupportApi]) {
                    message = @"当前微信版本较低,暂不支持";
                }
            }
            
            if ([SHPayManager sharedInstance].payComplateBlock) {
                
                [SHPayManager sharedInstance].payComplateBlock(
                                                               @{@"isSuccess" : @(false),
                                                                 @"message": message});
                [SHPayManager sharedInstance].payComplateBlock = nil;
            } else {
                [[NSNotificationCenter defaultCenter] postNotificationName:SHWXPayFailNotification object:nil userInfo:@{@"message" : message}];
            }
        }
    }];
}

+ (void)doLoginComplate:(void (^)(NSDictionary * _Nonnull))complate {
    
    [SHPayManager sharedInstance].loginComplateBlock = nil;
    [SHPayManager sharedInstance].loginComplateBlock = complate;
    
    //构造SendAuthReq结构体
    SendAuthReq* req = [[SendAuthReq alloc] init];
    req.scope = @"snsapi_userinfo";
    req.state = @"wxlogin_getuserinfo";
    //第三方向微信终端发送一个SendAuthReq消息结构
    [WXApi sendReq:req completion:^(BOOL success) {
        if (!success) {
            if ([SHPayManager sharedInstance].loginComplateBlock) {
                
                NSString *message = @"发送请求到微信失败，请稍后再试";
                
                [SHPayManager sharedInstance].loginComplateBlock(
                                                               @{@"isSuccess":@(false),
                                                                 @"message":message});
                [SHPayManager sharedInstance].loginComplateBlock = nil;
            } else {
                [[NSNotificationCenter defaultCenter] postNotificationName:SHWXLoginFailNotification object:nil userInfo:@{@"message":@"发送请求到微信失败，请稍后再试"}];
            }
        }
    }];
    
}

/*
 * Contact info@enormego.com if you're the author and we'll update this comment to reflect credit
 */
/*
 * Returns the MD5 value of the string
 */
+ (NSString *)md5:(NSString *)cself
{
    const char *  string = [cself UTF8String];
    unsigned char result[16];

    CC_LONG lenth = (CC_LONG)strlen(string);
    CC_MD5(string, lenth, result);
    NSString *hash = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                                                result[0], result[1], result[2], result[3], result[4], result[5],
                                                result[6], result[7], result[8], result[9], result[10], result[11],
                                                result[12], result[13], result[14], result[15]];

    return [hash lowercaseString];
}

/// 微信纯文本分享
/// @param title 文本
/// @param isFirendCircle 是否分享到朋友圈
+ (void)shareTitle:(NSString *)title
      firendCircle:(BOOL)isFirendCircle {
    SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
    req.bText = YES;
    req.text = title;
    req.scene = isFirendCircle ? WXSceneTimeline : WXSceneSession;
    [WXApi sendReq:req completion:^(BOOL success) {
        
    }];
}

/// 微信纯图片分享
/// @param imageData 文本
/// @param isFirendCircle 是否分享到朋友圈
+ (void)shareImageData:(NSData *)imageData
            thumbImage:(NSData *)thumbImageData
          firendCircle:(BOOL)isFirendCircle {
    
    WXImageObject *imageObject = [WXImageObject object];
    imageObject.imageData = imageData;

    WXMediaMessage *message = [WXMediaMessage message];
    message.thumbData = thumbImageData;
    message.mediaObject = imageObject;
    
    SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
    req.bText = NO;
    req.message = message;
    req.scene = isFirendCircle ? WXSceneTimeline : WXSceneSession;
    [WXApi sendReq:req completion:^(BOOL success) {
        
    }];
}

/// 微信
/// @param title 文本
/// @param description 描述
/// @param thumbImage 缩略图
/// @param webpageUrl 跳转的地址
/// @param isFirendCircle 是否分享到朋友圈
+ (void)shareTitle:(NSString *)title
       description:(NSString *)description
        thumbImage:(UIImage *)thumbImage
        webpageUrl:(NSString *)webpageUrl
      firendCircle:(BOOL)isFirendCircle {
    
    WXWebpageObject *webpageObject = [WXWebpageObject object];
    webpageObject.webpageUrl = webpageUrl;
    WXMediaMessage *message = [WXMediaMessage message];
    message.title = title;
    message.description = description;
    
    if (thumbImage) {
        NSData *imageData = UIImageJPEGRepresentation( thumbImage , 1.0);
        if (imageData.length > 60000) {
            thumbImage = [self imageSizeWithScreenImage:thumbImage];
        }
    }
    
    [message setThumbImage:thumbImage];
    message.mediaObject = webpageObject;
    SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
    req.bText = NO;
    req.message = message;
    req.scene = isFirendCircle ? WXSceneTimeline : WXSceneSession;
    [WXApi sendReq:req completion:^(BOOL success) {
        
    }];
}

/*! @brief 收到一个来自微信的请求，第三方应用程序处理完后调用sendResp向微信发送结果
 *
 * 收到一个来自微信的请求，异步处理完成后必须调用sendResp发送处理结果给微信。
 * 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
 * @param req 具体请求内容，是自动释放的
 */
- (void)onReq:(BaseReq*)req {
    
    // 微信内部打开应用回到这里    
}

- (void)gainWeChatInfo:(NSString *)code {
    
    NSString *url =[NSString stringWithFormat:@"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%@&secret=%@&code=%@&grant_type=authorization_code", [SHPayManager sharedInstance].appid, [SHPayManager sharedInstance].appSecret, code];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURL *zoneUrl = [NSURL URLWithString:url];
        NSString *zoneStr = [NSString stringWithContentsOfURL:zoneUrl encoding:NSUTF8StringEncoding error:nil];
        NSData *data = [zoneStr dataUsingEncoding:NSUTF8StringEncoding];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (data){
                NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
//                info.openID = dic[@"openid"];
//                info.unionID = dic[@"unionid"];
//                info.accessToken = dic[@"access_token"];
                [self getUserInfo:dic[@"access_token"] openid:dic[@"openid"]];
                
            } else {
                if ([SHPayManager sharedInstance].loginComplateBlock) {
                    [SHPayManager sharedInstance].loginComplateBlock(
                                                                   @{@"isSuccess" : @(false),
                                                                     @"message" : @"获取openid失败"});
                    [SHPayManager sharedInstance].loginComplateBlock = nil;
                } else {
                    [NSNotificationCenter.defaultCenter postNotificationName:SHWXLoginFailNotification object:nil userInfo:@{@"message" : @"获取openid失败"}];
                }
            }
        });
    });
}

-(void)getUserInfo:(NSString *)accessToken openid:(NSString *)openid {
    // https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
    
    NSString *url =[NSString stringWithFormat:@"https://api.weixin.qq.com/sns/userinfo?access_token=%@&openid=%@", accessToken, openid];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURL *zoneUrl = [NSURL URLWithString:url];
        NSString *zoneStr = [NSString stringWithContentsOfURL:zoneUrl encoding:NSUTF8StringEncoding error:nil];
        NSData *data = [zoneStr dataUsingEncoding:NSUTF8StringEncoding];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (data) {
                NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                /*
                 {
                 city = Haidian;
                 country = CN;
                 headimgurl = "http://wx.qlogo.cn/mmopen/FrdAUicrPIibcpGzxuD0kjfnvc2klwzQ62a1brlWq1sjNfWREia6W8Cf8kNCbErowsSUcGSIltXTqrhQgPEibYakpl5EokGMibMPU/0";
                 language = "zh_CN";
                 nickname = "xxx";
                 openid = oyAaTjsDx7pl4xxxxxxx;
                 privilege =     (
                 );
                 province = Beijing;
                 sex = 1;
                 unionid = oyAaTjsxxxxxxQ42O3xxxxxxs;
                 }
                 */
//                info.nickname = [dic objectForKey:@"nickname"];
//                info.headImageURL = [dic objectForKey:@"headimgurl"];
                
                if ([SHPayManager sharedInstance].loginComplateBlock) {
                    [SHPayManager sharedInstance].loginComplateBlock(
                                                                   @{@"isSuccess" : @(true),
                                                                     @"info" : dic,
                                                                     @"message" : @"获取信息成功"
                                                                   });
                    [SHPayManager sharedInstance].loginComplateBlock = nil;
                } else {
                    // 将这块的数据抛出去
                    [NSNotificationCenter.defaultCenter postNotificationName:SHWXLoginSuccessNotification object:nil userInfo:dic];
                }
            } else {
                [NSNotificationCenter.defaultCenter postNotificationName:SHWXLoginFailNotification object:nil userInfo:@{@"message" : @"获取信息失败"}];
            }
        });
        
    });
}


/*! @brief 发送一个sendReq后，收到微信的回应
 *
 * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
 * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
 * @param resp 具体的回应内容，是自动释放的
 */
- (void)onResp:(BaseResp *)resp {
    if ([resp isKindOfClass:SendAuthResp.class]) {
        /**
         * 微信处理完第三方程序的认证和权限申请后向第三方程序回送的处理结果。
         *
         * 第三方程序要向微信申请认证，并请求某些权限，需要调用WXApi的sendReq成员函数，向微信终端发送一个SendAuthReq消息结构。
         * 微信终端处理完后会向第三方程序发送一个SendAuthResp。
         **/
        SendAuthResp *authResp = (SendAuthResp*)resp;
        if (authResp.code.length && resp.errCode == WXSuccess) {
            // 获取微信openid
            [self gainWeChatInfo:authResp.code];
        } else {
            NSString *errorMSG = @"";
            switch (resp.errCode) {
                case WXSuccess:
                    break;
                case WXErrCodeCommon:
                    errorMSG = @"登录失败";
                    break;
                case WXErrCodeUserCancel:
                    errorMSG = @"取消登录";
                    break;
                    
                case WXErrCodeSentFail:
                    errorMSG = @"发送失败";
                    break;
                case WXErrCodeAuthDeny:
                    errorMSG = @"授权失败";
                    break;
                case WXErrCodeUnsupport:
                    errorMSG = @"不支持的类型";
                    break;
                    
                default:
                    break;
            }
            if ([SHPayManager sharedInstance].loginComplateBlock) {
                [SHPayManager sharedInstance].loginComplateBlock(
                                                               @{@"isSuccess" : @(false),
                                                                 @"message" : errorMSG});
                [SHPayManager sharedInstance].loginComplateBlock = nil;
            } else {
                [NSNotificationCenter.defaultCenter postNotificationName:SHWXLoginFailNotification object:nil userInfo:@{@"message" : errorMSG}];
            }
        }
    } else if([resp isKindOfClass:SendMessageToWXResp.class]) {
        /**
         * 微信终端向第三方程序返回的SendMessageToWXReq处理结果。
         *
         * 第三方程序向微信终端发送SendMessageToWXReq后，微信发送回来的处理结果，该结果用SendMessageToWXResp表示。
         */
        NSString *errorMSG = @"";
        switch (resp.errCode) {
            case WXSuccess:
                errorMSG = @"分享成功";
                break;
            case WXErrCodeCommon:
                errorMSG = @"分享失败";
                break;
            case WXErrCodeUserCancel:
                errorMSG = @"您已取消分享";
                break;
                
            case WXErrCodeSentFail:
                errorMSG = @"发送失败";
                break;
            case WXErrCodeAuthDeny:
                errorMSG = @"授权失败";
                break;
            case WXErrCodeUnsupport:
                errorMSG = @"不支持的类型";
                break;
                
            default:
                break;
        }
        
        [NSNotificationCenter.defaultCenter postNotificationName:SHWXShareResultNotification object:nil userInfo:@{@"message":errorMSG}];
        
    } else if([resp isKindOfClass:[PayResp class]]){
        //支付返回结果，实际支付结果需要去 业务方服务器端查询
        if (resp.errCode == WXSuccess) {
            if ([SHPayManager sharedInstance].payComplateBlock) {
                [SHPayManager sharedInstance].payComplateBlock(
                                                               @{@"isSuccess":@(true),
                                                                 @"message":@"支付成功"});
                [SHPayManager sharedInstance].payComplateBlock = nil;
            } else {
                [[NSNotificationCenter defaultCenter] postNotificationName:SHWXPaySuccessNotification object:nil userInfo:@{@"message":@"支付成功"}];
            }
        } else {
            if ([SHPayManager sharedInstance].payComplateBlock) {
                [SHPayManager sharedInstance].payComplateBlock(
                                                               @{@"isSuccess":@(false),
                                                                 @"message":resp.errStr?:@""});
                [SHPayManager sharedInstance].payComplateBlock = nil;
            } else {
                [[NSNotificationCenter defaultCenter] postNotificationName:SHWXPayFailNotification object:nil userInfo:@{@"message":resp.errStr?:@""}];
            }
        }
    }
}


// 重绘
/// 返回一张不超过屏幕尺寸的 image
+ (UIImage *)imageSizeWithScreenImage:(UIImage *)image {
    CGFloat imageWidth = image.size.width;
    CGFloat imageHeight = image.size.height;
    CGSize screenSize = UIScreen.mainScreen.bounds.size;
    CGFloat screenWidth = screenSize.width * 0.3;
    CGFloat screenHeight = screenSize.height * 0.3;
    
    if (imageWidth <= screenWidth && imageHeight <= screenHeight) {
        return image;
    }
    
    CGFloat max = MAX(imageWidth, imageHeight);
    CGFloat scale = max / (screenHeight * 2.0);
    
    CGSize size = CGSizeMake(imageWidth / scale, imageHeight / scale);
    UIGraphicsBeginImageContext(size);
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}



@end
